/**
 * Widget module
 */
import React from 'react';

import WidgetsProvider from './WidgetsProvider';
import consts from '../../../../utils/consts';
import tool from '../../../../utils/tool';
import widgetTypes from '../../../../consts/widgetTypes';
import zoomProvider from '../../../../utils/zoomProvider';
import dataProvider from '../../../../utils/dataProvider';
import storage from '../../../../utils/storage';

class Widget extends React.Component {
    componentWillMount() {
        this.transform = this.props.transform;
        this.widgets = WidgetsProvider;
        this.initOption();
        this.initStatus();
    }
    componentDidMount() {
        const { widget } = this.props;
        this.initElements();
        if (widget.type != consts.WIDGET_TYPE.FIXEDBTN) this.draggable();
        this.bindEvent();
        if (this.option.resizable) this.resizable();
    }
    shouldComponentUpdate(nextProps) {
        if(nextProps.selectedWidgetIds.length >0 || this.props.selectedWidgetIds.length >0){
            // 获取真正修改的id
            const objWidgetIds = {};
            const selectedWidgetIds = [].concat(nextProps.selectedWidgetIds, this.props.selectedWidgetIds);
            const changedWidgetIds = [];
            selectedWidgetIds.forEach((id) => {
                objWidgetIds[id] = objWidgetIds[id] ? 2 : 1;
            });
            for (const id in objWidgetIds) {
                if (objWidgetIds[id] === 1) changedWidgetIds.push(id);
            }
            if (changedWidgetIds.indexOf(this.props.widget.widget_id) !== -1) return true;
        }
        if (this.props.widget && nextProps.widget) {
            if (this.props.widget.timestamp !== nextProps.widget.timestamp) return true;
        }
        if (this.props.transform.offset_x !== nextProps.transform.offset_x) return true;
        return false;
    }

    componentDidUpdate() {
        // if (this.elements.widget) this.upHandles(this.elements.widget);
        console.log('我更新了', this.props.widget.widget_id);
    }
    initElements() {
        const { widget } = this.props;
        this.elements = {
            widget: $(`#wgt-id-${widget.id}`),
        };
    }
    // 初始化全局状态
    initStatus() {
        this.status = {
            dragging: false,
            history: false,
            lastValidSize: null,
            lastValidposition: null,
            startPosition: {},
            selectedWidgetStartPosition: {},
        };
    }
    // 初始化组件能完成的动作
    initOption() {
        const { widget } = this.props;
        const type = widget.type;
        this.option = {
            positionable: true,
            draggable: true,
            resizable: true,
            aspectRatio: true,
        };
        if (consts.VECTOR_WIDGETS.indexOf(type) === -1) {
            switch (type) {
            case widgetTypes.MUSIC:
            case widgetTypes.THREED:
            case widgetTypes.LOOKERS:
                this.option.resizable = this.option.aspectRatio = false;
                break;
            case widgetTypes.FIXEDBTN:
                this.option.resizable = this.option.draggable = false;
                break;
            }
        } else {
            switch (type) {
            case widgetTypes.TEXT:
                this.option.resizable = true;
                this.option.aspectRatio = false;
                break;
            case widgetTypes.REDBAG:
            case widgetTypes.HOPEBANK:
                this.option.resizable = this.option.aspectRatio = true;
                break;
            case widgetTypes.GRAPH:
                this.option.aspectRatio = false;
                break;
            default:
                this.option.resizable = false;
            }
        }
    }
    // 初始化组件的位置
    initPosition() {
        const { widget, transform } = this.props;
        this.transform = transform;
        if (!this.transform) {
            return;
        }
        this.position = tool.getPosition(widget, this);
        this.initResizeLock();
//        this.checkoutResize();
    }
    initResizeLock() { // 初始化大小缩放锁定状态
        const { widget, transform, fromTemplate } = this.props;
        const opt = this.option;
        if (fromTemplate || !this.elements) return false;
        if (widget.resize_lock == 0) {
            this.option.aspectRatio = false;
            this.elements.widget.resizable('destroy');
            this.resizable();
            return;
        } else if (widget.resize_lock == 1) {
            this.option.aspectRatio = true;
            this.elements.widget.resizable('destroy');
            this.resizable();
        }
        if (widget.resize_lock != -1) return;
        if (opt.resizable == undefined || opt.resizable) { // 能够resize
            if (opt.aspectRatio == undefined || opt.aspectRatio) widget.resize_lock = 1; // 宽高比锁定
            else widget.resize_lock = 0;
        } else {
            widget.resize_lock = -1;
        }
    }
    positionTogether (position){
        // var root = this.props.root;
        const{widgets} = this.props;
        var data = storage.data;
        if (data.selectedWidgetIds.indexOf(widget.id) == -1) return;
        if (data.selectedWidgetIds.length > 0){
            var distanceTop, distanceLeft, index, openWidgetIds, scale;
            scale = zoomProvider.scale();
            distanceTop = position.top - this.status.startPosition.top * scale;
            distanceLeft = position.left - this.status.startPosition.left * scale;
            openWidgetIds = [].concat(data.selectedWidgetIds);
            index = openWidgetIds.indexOf(widget.id);
            openWidgetIds.splice(index, 1);
            for (var i = 0; i < openWidgetIds.length; i++) {
                var widgetId = openWidgetIds[i];
                var widget = dataProvider.getSpecifyWidgetById(widgetId);
                var widgetEl = $(consts.WIDGET_CLASS_PREFIX + widgetId);
                var widgetStartPosition = $.extend(true, {}, this.status.selectedWidgetStartPosition[widgetId]);
                widgetStartPosition.top += distanceTop;
                widgetStartPosition.left += distanceLeft;
                widgetStartPosition.width = widget.width;
                widgetStartPosition.height = widget.height;
                widgetEl.css(widgetStartPosition);

                var offset = tool.borderOffsetToCenterOffset(widgetStartPosition, this.transform);
                widget.offset_x = offset.x;
                widget.offset_y = offset.y;

                dataProvider.saveWidgetPosition(data.page.page_id, widget);
                // root.updateLocaleSelectedWidget(widget);
            }
        }
    }
    preventStart (e, ui){
        var widget = this.props.widget;
        var position, scale, data = storage.data;

        this.status.dragging = true;
        if (data.selectedWidgetIds.length <= 1){
            data.selectedWidgetId = widget.id;
        }
        scale = zoomProvider.scale();
        position = this.position;
        position = {
            top: position.top,
            left: position.left / scale
        };

        this.status.startPosition = $.extend({}, position);
        if (data.selectedWidgetIds.length > 1){
            var openWidgetIds = $.extend(true, [], data.selectedWidgetIds),
                index = openWidgetIds.indexOf(widget.id);
            openWidgetIds.splice(index, 1);
            for (var i = 0; i < openWidgetIds.length; i++){
                var widget_id = openWidgetIds[i];
                var widgetEl = $(consts.WIDGET_CLASS_PREFIX + widget_id);
                var widgetPosition = widgetEl.position();
                widgetPosition.left = widgetPosition.left / scale;
                this.status.selectedWidgetStartPosition[widget_id] = widgetPosition;
            }
            for (var i = 0; i < data.selectedWidgetIds.length; i++){
                var widget_id = data.selectedWidgetIds[i],
                    oldWidget = $.extend(true, {}, dataProvider.getSpecifyWidgetById(widget_id));
                dataProvider.updateOldWidgets(oldWidget);
            }
        } else {
            var oldWidget = dataProvider.getSpecifyWidgetById(widget.id);
            dataProvider.updateOldWidgets(oldWidget);
        }

        // 同步选中3d场景中的素材
        eventHelper.trigger(consts.EVENTS.THREED_WIDGET_SELECTED, widget.id);
    }
    broadcastPosition (ev, ui){
        var position, scale;
        if (ui.size){
            tool.updateFontSize(this, ui);
            tool.workAroundBugInjQueryUI(this, ui);
            $.extend(true, {}, this.position, {
                fontSize: tool.getFontSizeByWidth(ui.position.height)
            });
        }
        if (!ui.size){
            scale = zoomProvider.scale();
            position = {
                left: ui.position.left / scale,
                top: ui.position.top / scale
            }
        } else {
            position = {
                left: ui.position.left,
                top: ui.position.top
            }
        }
        $.extend(this.position, position, ui.size);
        this.elements.widget.css(position);
        this.positionTogether($.extend(true, {}, position));
        this.upHandles(this.elements.widget);
    }
    updateLocalWidget (){
        var root = this.props.root;
        var widget = this.props.widget;
        root.updateLocaleWidget(widget);
        // 检查元件是否有路径动效，随offset改变更新路径点
        root.updateWidgetTimelines(widget);
    }
    updatePositionModel (){
        var widget = this.props.widget;
        var offset = tool.borderOffsetToCenterOffset(this.position, this.transform);
        var position = {
            offset_x: offset.x,
            offset_y: offset.y,
            width: this.position.width,
            height: this.position.height,
            fontSize: tool.getFontSizeByWidth(this.position.height)
        };
        $.extend(true, widget, position);
    }
    savePosition (){
        var widget = this.props.widget;
        if (!widget.unsaved){
            var oldWidget = $.extend(true, {}, dataProvider.oldWidgets[widget.id]),
                newWidget = $.extend(true, {}, widget),
                root = this.props.root;
            this.updatePositionModel();
            widget.is_saved = true;
            dataProvider.saveWidgetPosition(storage.data.page.page_id, widget);
            historyProvider.execute(new WidgetPropertyCommand(storage.data.page, oldWidget, newWidget, root, dataProvider));
            eventHelper.trigger(consts.EVENTS.THREED_WIDGET_PROPERTY_CHANGED, widget);

            this.updateLocalWidget();
        }
    }
    debounceSavePosition (ev, ui){
        var data = storage.data;
        var widget = this.props.widget;
        this.status.dragging = false;
        if (ui.size) tool.workAroundBugInjQueryUI(this, ui);
        if (widget.property_changed) delete widget.property_changed;
        if (data.selectedWidgetIds.length > 1){
            var distanceTop, distanceLeft, index, openWidgetIds;
            openWidgetIds = [].concat(data.selectedWidgetIds);
            index = openWidgetIds.indexOf(widget.id);
            openWidgetIds.splice(index, 1);

            var oldWidgets = [], newWidgets = [];
            for (var i = 0; i < data.selectedWidgetIds.length; i++){
                var widget_id, widgetEl, oldWidget, newWidget;
                widget_id = data.selectedWidgetIds[i];
                widgetEl = $(consts.WIDGET_CLASS_PREFIX + widget_id);
                this.status.history = true;
                this.savePosition();
            };
        } else {
            this.savePosition();
        }
    }

    upHandles($element) {
        const widget = this.props.widget;
        // 以元件中心为坐标系
        let this_sw = $element.find('.ui-resizable-sw'),
            this_ne = $element.find('.ui-resizable-ne'),
            this_nw = $element.find('.ui-resizable-nw'),
            this_se = $element.find('.ui-resizable-se'),
            this_e = $element.find('.ui-resizable-e'),
            this_s = $element.find('.ui-resizable-s'),
            this_n = $element.find('.ui-resizable-n'),
            this_w = $element.find('.ui-resizable-w');
        let width = $element.width() || widget.width,
            height = $element.height() || widget.height,
            r = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)) * 0.5,
            tan_a = height / width,
            r_z = parseInt(widget.rotate_z),
            r_a = Math.atan(tan_a) / 2 / Math.PI * 360,
            r_c = r_a + r_z > 360 ? (r_a + r_z) - 360 : r_a + r_z,
            r_s = r_z + 180,
            left,
            top,
            bottom,
            right,
            left_c,
            right_c,
            top_c,
            bottom_c;
        r_z >= 360 && (r_z %= 360);
        r_z < 0 && (r_z += 360);
        r_s >= 360 && (r_s %= 360);
        r_s < 0 && (r_s += 360);
        left = r * Math.cos(2 * Math.PI / 360 * r_a) - r * Math.cos(2 * Math.PI / 360 * (r_c)) - 5;
        top = r * Math.sin(2 * Math.PI / 360 * r_a) - r * Math.sin(2 * Math.PI / 360 * (r_c)) - 5;
        right = r * Math.cos(2 * Math.PI / 360 * r_a) - r * Math.cos(2 * Math.PI / 360 * (r_a - r_z)) - 5;
        bottom = r * Math.sin(2 * Math.PI / 360 * r_a) - r * Math.sin(2 * Math.PI / 360 * (r_a - r_z)) - 5;

        left_c = width / 2 - width / 2 * Math.cos(2 * Math.PI / 360 * r_z) - 5;
        top_c = height / 2 - width / 2 * Math.sin(2 * Math.PI / 360 * r_z) - 2.5;

        right_c = width / 2 - height / 2 * Math.sin(2 * Math.PI / 360 * (r_z));
        bottom_c = height / 2 - height / 2 * Math.cos(2 * Math.PI / 360 * (r_z)) - 5;
        if (!r_z) {
            this_n.css({ cursor: 'n-resize' });
            this_w.css({ left: '-5px' });
            this_w.css({ top: `${height / 2 - 5}px` });
            this_w.css({ cursor: 'w-resize' });
            this_s.css({ cursor: 's-resize' });
            this_e.css({ cursor: 'e-resize' });
        }
        if (r_c) {
            // 左上和右下
            this_nw.css({ left: `${left}px` });
            this_nw.css({ top: `${top}px` });

            this_se.css({ right: `${left}px` });
            this_se.css({ bottom: `${top}px` });
            // 右上和左下
            this_ne.css({ right: `${right}px` });
            this_ne.css({ top: `${bottom}px` });

            this_sw.css({ left: `${right}px` });
            this_sw.css({ bottom: `${bottom}px` });
//                    左
            this_w.css({ left: `${left_c}px` });
            this_w.css({ top: `${top_c}px` });
//                    右
            this_e.css({ right: `${left_c}px` });
            this_e.css({ bottom: `${top_c}px` });
//                    上
            this_n.css({ right: `${right_c - 2.5}px` });
            this_n.css({ top: `${bottom_c}px` });

            this_s.css({ left: `${right_c - 2.5}px` });
            this_s.css({ bottom: `${bottom_c}px` });
        }
        if (r_z <= 22 || r_z >= 338) {
            this_ne.css('cursor', 'ne-resize');
            this_se.css('cursor', 'se-resize');
            this_nw.css('cursor', 'nw-resize');
            this_sw.css('cursor', 'sw-resize');
            this_e.css('cursor', 'e-resize');
            this_w.css('cursor', 'w-resize');
            this_s.css('cursor', 's-resize');
            this_n.css('cursor', 'n-resize');
        }
        if (r_z > 22 || r_z <= 67) {
            this_ne.css('cursor', 'e-resize');
            this_se.css('cursor', 's-resize');
            this_nw.css('cursor', 'n-resize');
            this_sw.css('cursor', 'w-resize');
            this_e.css('cursor', 'se-resize');
            this_w.css('cursor', 'nw-resize');
            this_s.css('cursor', 'sw-resize');
            this_n.css('cursor', 'ne-resize');
        }
        if (r_z > 67 || r_z <= 112) {
            this_ne.css('cursor', 'se-resize');
            this_se.css('cursor', 'sw-resize');
            this_nw.css('cursor', 'ne-resize');
            this_sw.css('cursor', 'nw-resize');
            this_e.css('cursor', 's-resize');
            this_w.css('cursor', 'n-resize');
            this_s.css('cursor', 'w-resize');
            this_n.css('cursor', 'e-resize');
        }
        if (r_z > 112 || r_z <= 157) {
            this_ne.css('cursor', 's-resize');
            this_se.css('cursor', 'w-resize');
            this_nw.css('cursor', 'e-resize');
            this_sw.css('cursor', 'n-resize');
            this_e.css('cursor', 'sw-resize');
            this_w.css('cursor', 'ne-resize');
            this_s.css('cursor', 'nw-resize');
            this_n.css('cursor', 'se-resize');
        }
        if (r_z > 157 || r_z <= 202) {
            this_ne.css('cursor', 'sw-resize');
            this_se.css('cursor', 'nw-resize');
            this_nw.css('cursor', 'se-resize');
            this_sw.css('cursor', 'ne-resize');
            this_e.css('cursor', 'w-resize');
            this_w.css('cursor', 'e-resize');
            this_s.css('cursor', 'n-resize');
            this_n.css('cursor', 's-resize');
        }
        if (r_z > 202 || r_z <= 247) {
            this_ne.css('cursor', 'w-resize');
            this_se.css('cursor', 'n-resize');
            this_nw.css('cursor', 's-resize');
            this_sw.css('cursor', 'e-resize');
            this_e.css('cursor', 'nw-resize');
            this_w.css('cursor', 'se-resize');
            this_s.css('cursor', 'ne-resize');
            this_n.css('cursor', 'sw-resize');
        }
        if (r_z > 247 || r_z <= 292) {
            this_ne.css('cursor', 'nw-resize');
            this_se.css('cursor', 'ne-resize');
            this_nw.css('cursor', 'sw-resize');
            this_sw.css('cursor', 'se-resize');
            this_e.css('cursor', 'n-resize');
            this_w.css('cursor', 's-resize');
            this_s.css('cursor', 'e-resize');
            this_n.css('cursor', 'w-resize');
        }
        if (r_z > 292 || r_z <= 337) {
            this_ne.css('cursor', 'n-resize');
            this_se.css('cursor', 'e-resize');
            this_nw.css('cursor', 'w-resize');
            this_sw.css('cursor', 's-resize');
            this_e.css('cursor', 'ne-resize');
            this_w.css('cursor', 'sw-resize');
            this_s.css('cursor', 'se-resize');
            this_n.css('cursor', 'nw-resize');
        }
        if (r_z == 0) {
            this_ne.css('cursor', 'ne-resize');
            this_se.css('cursor', 'se-resize');
            this_nw.css('cursor', 'nw-resize');
            this_sw.css('cursor', 'sw-resize');
            this_e.css('cursor', 'e-resize');
            this_w.css('cursor', 'w-resize');
            this_s.css('cursor', 's-resize');
            this_n.css('cursor', 'n-resize');
        }
    }
    draggable() {
        const { widget, fromTemplate } = this.props;
        this.elements.widget.draggable({
            containment: '.editor-canvas',
            handle: '.prevent-interaction',
            start: (e, ui) => this.preventStart(e, ui),
            drag: (e, ui) => this.broadcastPosition(e, ui),
            stop: (e, ui) => this.debounceSavePosition(e, ui),
            transform: this.transform,
            area: this.area,
            widget,
            zoomProvider,
            snap: true,
            snapTolerance: 5,
            // view: storage.data.CONST.view,
            view: is.CONST.view,
        });
    }
    resizable() {
        const { widget, fromTemplate } = this.props;
        if (fromTemplate || !this.elements) return false;
        let minWidth,
            minHeight;
            minWidth = minHeight = (widget.type == widgetTypes.GRAPH ? consts.MIN_BUTTON_SIZE : 15);
        this.elements.widget.resizable({
            minWidth,
            minHeight,
            handles: 'e,s,n,w,ne,se,sw,nw',
            containment: '.editor-canvas',
            aspectRatio: this.option.aspectRatio,
            start: function () {
                const widget = this.props.widget;
                widget.sizeChanged = true;
                this.preventStart();
            }.bind(this),
            resize: (e, ui) => this.broadcastPosition(e, ui),
            stop: (e, ui) => this.debounceSavePosition(e, ui),
            angle_x: widget.rotate_x,
            angle_y: widget.rotate_y,
            angle_z: widget.rotate_z,
            width: widget.width,
            height: widget.height,
            zoomProvider,
        });
        this.upHandles(this.elements.widget);
    }
    bindEvent() {
        const contextmenuClass = 'widget-context-menu';
        this.elements.widget.contextmenu({
            target: `.${contextmenuClass}`,
            onItem: this.handleOnContextMenu,
        });
        const fromTemplate = this.props.fromTemplate;
        // const root = this.props.root;
        // if (fromTemplate) root.updateMenus.call(null, 'widget');
    }
    handleOnContextMenu(el, e) {
        return;
        e.preventDefault();

        const data = storage.data;
        const root = this.props.root;
        const widget = this.props.widget;

        const menuItem = $(e.target || e.srcElement);
        const action = menuItem.attr('data-action');

        const results = [widget.id];
        const selectedWidgetIds = data.selectedWidgetIds;

        this.elements.widget.data('context').closemenu();

        if (action) {
            switch (action) {
            case 'copy':
                root.updateMenus.call(null, 'editor');
                storage.data.widgetsCopy = $.extend(true, {}, widget);
                root.updateMenus('editor');
                break;
            case 'hideMe':
                widget.visible = false;
//                    root.updateSpecifyWidget(widget);
                data.widgetAllVisible = false;
                dataProvider.widgetVisibleChanged(widget);
                break;
            case 'toggleOther':
                data.toggleAllVisible = !data.toggleAllVisible;
                data.widgetAllVisible = data.toggleAllVisible;
                dataProvider.toggleAll(widget, data.toggleAllVisible);
                root.updateMenus.call(null, 'widget');
                break;
            case 'delete':
                    // 多选素材时支持全部删除
                var parent = this.props.parent;
                parent.deleteSeletedWidget(widget.id);
                break;
            }
            root.updateMenus('editor');
        }
        return false;
    }
    createWidget() {
        // let root = this.props.root,
        const widget = this.props.widget;
        const type = consts.WIDGET_TYPE_MAPPING[widget.type];
        const item = React.createElement(
            this.widgets[type],
            {
                // root,
                widget,
            },
        );
        return item;
    }
    render() {
        this.initPosition();
        const { widget, selectedWidgetIds } = this.props;
        const position = $.extend(true, { display: widget.visible ? 'block' : 'none' }, this.position);
        const isVectorWidget = consts.VECTOR_WIDGETS.indexOf(widget.type) != -1;

        const innerNode = this.createWidget();
        let renderNode = '';
        const rotate_y = -widget.rotate_y;
        const rStyle = {
            transform: `rotateX(${widget.rotate_x}deg)` + `rotateY(${rotate_y}deg)` + `rotateZ(${widget.rotate_z}deg)`,
        };

        if (isVectorWidget) {
            renderNode =
              (
                <div className="render-widget" style={rStyle}>
                  {innerNode}
                </div>
              );
        } else {
            renderNode =
            (
              <div>
                <del className="prevent-interaction" style={rStyle} />
                <div className="render-widget" style={rStyle}>
                  {innerNode}
                </div>
              </div>
            );
        }
        return (
          <figure
            id={`wgt-id-${widget.id}`}
            data-id={widget.id}
            style={position}
            className={`btg-widget wgt-action-${widget.type}${selectedWidgetIds.indexOf(widget.id) !== -1 ? ' focus ' : ' '}`}
          >
            {renderNode}
          </figure>
        );
    }
}

export default Widget;
